<template>
    <div class="bg-gray-100">
      <div class="container">
        <div class="dragger_wrap">
          <!-- 动态元素 -->
          <div 
            v-for="(element, index) in elements" 
            :key="index"
            class="drag-wrapper"
          >
            <div
              class="draggable dynamic-item"
              :style="{
                backgroundColor: element.color,
                transform: draggingIndex === index ? `translate(${offset.x}px, ${offset.y}px)` : ''
              }"
              @mousedown="startDrag(index, $event)"
            >
              {{ element.text }}
            </div>
          </div>
  
          <!-- 静态元素 -->
          <div class="drag-wrapper">
            <div class="static-item">111</div>
          </div>
          <div class="drag-wrapper">
            <div class="static-item">222</div>
          </div>
        </div>
      </div>
    </div>
  </template>
  
  <script setup>
  import { ref, reactive } from 'vue';
  
  const elements = ref([
    { text: '元素 1', color: '#1677ff' },
    { text: '元素 2', color: '#52c41a' },
    { text: '元素 3', color: '#faad14' },
    { text: '元素 4', color: 'red' },
  ]);
  
  const draggingIndex = ref(-1);
  const offset = reactive({ x: 0, y: 0 });
  const startPos = reactive({ x: 0, y: 0 });
  const wrapRects = ref([]);
  
  const startDrag = (index, e) => {
    draggingIndex.value = index;
    const wrapper = e.target.parentElement;
    
    // 记录所有包裹层的位置
    wrapRects.value = Array.from(document.querySelectorAll('.drag-wrapper'))
      .map(el => el.getBoundingClientRect());
    
    // 记录初始位置
    const rect = e.target.getBoundingClientRect();
    startPos.x = e.clientX - rect.left;
    startPos.y = e.clientY - rect.top;
  
    // 设置拖拽元素定位
    e.target.style.position = 'absolute';
    e.target.style.width = `${rect.width}px`;
    
    window.addEventListener('mousemove', handleDrag);
    window.addEventListener('mouseup', stopDrag);
  };
  
  const handleDrag = (e) => {
    if (draggingIndex.value === -1) return;
  
    // 计算相对包裹层的偏移
    const wrapperRect = wrapRects.value[draggingIndex.value];
    offset.x = e.clientX - wrapperRect.left - startPos.x;
    offset.y = e.clientY - wrapperRect.top - startPos.y;
  
    // 碰撞检测
    let targetIndex = -1;
    wrapRects.value.forEach((rect, index) => {
      if (index === draggingIndex.value) return;
      
      // 仅检测动态元素
      if (index >= elements.value.length) return;
  
      const centerX = rect.left + rect.width/2;
      const centerY = rect.top + rect.height/2;
      
      if (
        e.clientX > rect.left && 
        e.clientX < rect.right &&
        e.clientY > rect.top &&
        e.clientY < rect.bottom
      ) {
        targetIndex = index;
      }
    });
  
    // 实时交换
    if (targetIndex !== -1) {
      swapElements(draggingIndex.value, targetIndex);
      draggingIndex.value = targetIndex;
    }
  };
  
  const swapElements = (oldIndex, newIndex) => {
    [elements.value[oldIndex], elements.value[newIndex]] = 
      [elements.value[newIndex], elements.value[oldIndex]];
  };
  
  const stopDrag = () => {
    // 重置状态
    draggingIndex.value = -1;
    offset.x = 0;
    offset.y = 0;
    
    // 恢复元素定位
    document.querySelectorAll('.dynamic-item').forEach(el => {
      el.style.position = '';
      el.style.width = '';
      el.style.transform = '';
    });
    
    window.removeEventListener('mousemove', handleDrag);
    window.removeEventListener('mouseup', stopDrag);
  };
  </script>
  
  <style scoped>
  /* 包裹层样式 */
  .drag-wrapper {
    display: inline-block;
    width: 30%;
    min-height: 60px; /* 根据内容高度调整 */
    margin: 10px;
    position: relative;
  }
  
  /* 拖拽元素样式 */
  .draggable {
    cursor: move;
    user-select: none;
    padding: 1rem;
    border-radius: 0.375rem;
    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
    transition: transform 0.3s ease;
  }
  
  /* 静态元素样式 */
  .static-item {
    border: 1px solid #e5e7eb;
    color: #666;
    padding: 1rem;
    border-radius: 0.375rem;
    background: #f9fafb;
  }
  
  /* 容器布局 */
  .dragger_wrap {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
  }
  
  .container {
    max-width: 1280px;
    margin: 0 auto;
    padding: 2rem;
  }
  
  /* 拖拽时的样式 */
  .dynamic-item {
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    z-index: 1;
  }
  
  .dynamic-item:active {
    box-shadow: 0 8px 12px -2px rgba(0, 0, 0, 0.15);
    z-index: 1000;
    transition: none;
  }
  </style>